package com.itheima.gateway.filters;


import com.itheima.exception.UserException;
import com.itheima.gateway.service.TokenService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


/**
 * 全局过滤器
 * 实现ordered接口,重写getOrder返回,返回的值会作为当前过滤器的优先级,和order注解功能一样
 */
//@Order(-1) //当前过滤器在过滤器链的优先级,数值越小,优先级越高
@Component //将当前过滤器添加到spring容器中管理
@Slf4j
public class AuthorizeFilter implements GlobalFilter, Ordered {

    @Autowired
    private TokenService tokenService;

    //路径匹配器支持通配符
   // private static final AntPathMatcher PATH_MATCHER=new AntPathMatcher();


    /**
     *  处理当前请求，有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文，里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器
     * @return {@code Mono<Void>} 返回标示当前过滤器业务结束
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求参数
        ServerHttpRequest request = exchange.getRequest();

        //登录请求,放行
        String requestURI = request.getURI().toString();
        log.info("请求访问:{}",requestURI);

        if (requestURI.contains("/admin/login")|| requestURI.contains("/aliyun/oss/upload")){
            log.info("登录操作,放行");
            return chain.filter(exchange);
        }


        Object authorization = request.getHeaders().get("authorization");
        log.info("token为:{}",authorization);

        if(authorization == null  ){
           // throw new UserException(com.itheima.constant.HttpStatus.FORBIDDEN,"未登录");// token 是否为空
            //设置响应状态码401;未授权
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            //结束处理,直接返回响应
            return exchange.getResponse().setComplete();
        }

        //获取从jwt中获取 Payload 信息
        String[] jwt = authorization.toString().split(" ");
        log.info("jwt为:{}",jwt[1]);
        Claims claims = tokenService.getClaimsFromJwt(jwt[1].replace("]",""));
        //获取用户信息
        Object userName = claims.get("userName");

        try {
            if(userName==null){
               // throw new UserException(com.itheima.constant.HttpStatus.FORBIDDEN,"token已过期");
                //设置响应状态码401;未授权
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                //结束处理,直接返回响应
                return exchange.getResponse().setComplete();
            }
            log.info("已登录:{},放行",userName);
            return chain.filter(exchange);
        }catch(MalformedJwtException ex){
            //throw new UserException("token 格式不对",ex, com.itheima.constant.HttpStatus.FORBIDDEN);
        }catch(SignatureException ex){
            //throw new UserException("token 不对",ex, com.itheima.constant.HttpStatus.FORBIDDEN);
        }catch(ExpiredJwtException ex){
           // throw new UserException("token已过期",ex, com.itheima.constant.HttpStatus.FORBIDDEN);
        }

        //设置响应状态码401;未授权
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        //结束处理,直接返回响应
        return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
